package com.sunnyatwal.kettlebell;

import java.io.IOException;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.NumberPicker;
import android.widget.TextView;
import android.widget.Toast;

import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.view.ActionMode;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.sunnyatwal.kettlebell.db.WorkoutDatabase;
import com.sunnyatwal.kettlebell.db.WorkoutDatabaseSingleton;
import com.sunnyatwal.kettlebell.model.Exercise;
import com.sunnyatwal.kettlebell.model.ExerciseUnit;
import com.sunnyatwal.kettlebell.model.Rest;
import com.sunnyatwal.kettlebell.model.SubExercise;

public class EditWorkoutActivity extends SherlockActivity {
	
	private static final String TAG = "EditWorkoutActivity";
	
	private final static String INTENT_NAME_WORKOUT = "workout";
	private final static String INTENT_NAME_EXERCISE = "exercise";
	
	private static final int REQUEST_CODE_ADD_EXERCISE = 0;
	private static final int REQUEST_CODE_EDIT_EXERCISE = 1;
	
	private final static int INVALID_LIST_INDEX = -1;
	
	private int mSelectedItemIndex = INVALID_LIST_INDEX;
	
	private SubExerciseAdapter mAdapter;
	
	private Exercise mIntentExercise;
	
	ChangeListener mChangeListener = null;
	
	ActionMode mMode;
	
	
	@Override 
	protected void onStart() {
		Log.i(TAG, "onStart");
		super.onStart();
	}
	
	
	@Override
	protected void onStop() {
    	Log.i(TAG, "onStop");
    	super.onStop();
    }
	
	
	@Override
	protected void onRestart() {
		Log.i(TAG, "onRestart");
		super.onRestart();
	}
	
	
	@Override
	protected void onResume() {
		Log.i(TAG, "onResume");
		super.onResume();		    			
	}
	
	
	@Override
	protected void onDestroy() {
		Log.i(TAG, "onDestroy");
		super.onDestroy();
	}
	
	
	/*TODO: there is currently a bug where hitting back during an action 
	mode doesn't clear mSelectedItemIndex */
	@Override	
    public void onBackPressed() {
		Log.i(TAG, "onBackPressed");
		super.onBackPressed();
    }
	
	
	@Override
    protected void onCreate(Bundle savedInstanceState) {
		Log.i(TAG, "onCreate");
		
		super.onCreate(savedInstanceState);
		
    	setContentView(R.layout.activity_edit_workout);
    	
    	getActionBar().setDisplayHomeAsUpEnabled(false);
    	getActionBar().setDisplayShowTitleEnabled(false);
    	
    	//build the workout
    	if (getIntent().hasExtra(INTENT_NAME_WORKOUT)) {	
    		mIntentExercise = getIntent().getParcelableExtra(INTENT_NAME_WORKOUT);
    	}
    	else {
    		mIntentExercise = new Exercise(getString(R.string.string_new_workout));
    	}
    	
    	TextView name = (TextView) findViewById(R.id.edit_workout_name);
    	name.setText(mIntentExercise.getTitle());  
    	
    	//build listview from workout
		TouchInterceptor listview = (TouchInterceptor) findViewById(R.id.edit_workout_list);
		
    	mAdapter = new SubExerciseAdapter(this, R.layout.subexercise_row, mIntentExercise.getRoutine());	
		
		listview.setAdapter(mAdapter);
		listview.setDragListener(mDragListener);
		listview.setDropListener(mDropListener);
		listview.setOnItemClickListener(mClickListener);
					
		registerForContextMenu(listview); 
    }
	 
	
	@Override
    public void onContentChanged() {
		Log.i(TAG, "onContentChanged");
		
    	super.onContentChanged();
    	
    	TouchInterceptor listview = (TouchInterceptor) findViewById(R.id.edit_workout_list);
		View empty = findViewById(R.id.edit_workout_ListView_empty);
		listview.setEmptyView(empty);
    }
	
	
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    	Log.i(TAG, "onCreateOptionsMenu");
    	
    	getSupportMenuInflater().inflate(R.menu.activity_edit_workout, menu);
    	return super.onCreateOptionsMenu(menu);
    }
    
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    	Log.i(TAG, "onOptionsItemSelected");
    	
        switch (item.getItemId()) {
        
	        case android.R.id.home:
	        case R.id.menu_edit_workout_back:
	    		finish();
	    		break;
	    	
        	case R.id.menu_edit_workout_add_exercise:
				startEditExerciseActivityForResult();
				break;
			
        	case R.id.menu_edit_workout_add_rest:
        		editRest();
        		break;
        	
        	case R.id.menu_edit_workout_save:
	        	if (sendResultToManageWorkoutActivity()) {        		
	        		finish();
	        	}
	        	break;
        }
        
        return super.onOptionsItemSelected(item);
    }
    
    
	@Override 
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {     
		Log.i(TAG, "onActivityResult");
		
		boolean bResultSuccess = false;
		
		if (resultCode == Activity.RESULT_OK) {			
			if (requestCode == REQUEST_CODE_ADD_EXERCISE || requestCode == REQUEST_CODE_EDIT_EXERCISE) {				
				if(data.hasExtra(INTENT_NAME_EXERCISE)) {
					
					SubExercise exerciseResult = data.getParcelableExtra(INTENT_NAME_EXERCISE);
					
					if (exerciseResult != null) {
						if (requestCode == REQUEST_CODE_EDIT_EXERCISE && mSelectedItemIndex > INVALID_LIST_INDEX)
							bResultSuccess = mIntentExercise.setRoutineItem(mSelectedItemIndex, exerciseResult);
						else if (requestCode == REQUEST_CODE_ADD_EXERCISE)
							bResultSuccess = mIntentExercise.AddRoutineItem(exerciseResult);
					}					
				}							
			}												
		}
		
		if (!bResultSuccess)
			Log.i(TAG, "Activity Result failed");
		
		//Need to clear selected index when returning from prev. activity
		mSelectedItemIndex = INVALID_LIST_INDEX;
		
		mAdapter.notifyDataSetChanged();
	}

	
	/**
	 * Retrieves the currently selected exercise
	 * for edit
	 */
	private void editExercise() {
    	Log.i(TAG, "editExercise");
    	    	
		ExerciseUnit e = mIntentExercise.getRoutineItem(mSelectedItemIndex);
		
		if (e instanceof Rest)
			editRest();
		else
			startEditExerciseActivityForResult(e);
    }
	
	
	private void startEditExerciseActivityForResult() {
    	Log.i(TAG, "startEditExerciseActivityForResult");
    	
    	Intent intent = new Intent(this, EditExerciseActivity.class);
    	startActivityForResult(intent, REQUEST_CODE_ADD_EXERCISE);
    }
    
    
    private void startEditExerciseActivityForResult(ExerciseUnit e) {
    	Log.i(TAG, "startEditExerciseActivityForResult");
    	
		Intent intent = new Intent(this, EditExerciseActivity.class);
		
		intent.putExtra(INTENT_NAME_EXERCISE, e);
      	startActivityForResult(intent, REQUEST_CODE_EDIT_EXERCISE);
    }
	
	/**
	 * creates an alert dialog where a rest object can be created/updated
	 */
	private void editRest() {
		Log.i(TAG, "editRest");		
		
		final boolean bIndexValid = mSelectedItemIndex > INVALID_LIST_INDEX;
		
    	AlertDialog.Builder alert = new AlertDialog.Builder(EditWorkoutActivity.this);
    	
    	TextView title = new TextView(this);     	
    	String sTitle = getString(bIndexValid ? R.string.string_edit_rest : R.string.string_add_rest);     	
		title.setText(sTitle);    	
    	title.setPadding(10, 10, 10, 10);
    	title.setGravity(Gravity.CENTER);
    	title.setTextSize(20);
    	
    	alert.setCustomTitle(title);  
    	    	
    	LayoutInflater inflater = getLayoutInflater();
    	
    	View viewRest = inflater.inflate(R.layout.rest_picker, null);
    	    	
    	final NumberPicker npMins = (NumberPicker) viewRest.findViewById(R.id.rest_picker_mins);        	
    	npMins.setMinValue(0);
    	npMins.setMaxValue(59);
    	npMins.setWrapSelectorWheel(true);
    	
    	final NumberPicker npSecs = (NumberPicker) viewRest.findViewById(R.id.rest_picker_secs);
    	npSecs.setMinValue(0);
    	npSecs.setMaxValue(59);
    	npMins.setWrapSelectorWheel(true);
    	
    	if (bIndexValid) {
    		if (mIntentExercise.getRoutineItem(mSelectedItemIndex) instanceof Rest) {
	    		ExerciseUnit eUnit = mIntentExercise.getRoutineItem(mSelectedItemIndex);
	    		npMins.setValue(eUnit.getTotalTimeMinutes());
	    		npSecs.setValue(eUnit.getTotalTimeSeconds());
    		}
    	}
    	
    	String sMessage = bIndexValid ? getString(R.string.string_update) : getString(R.string.string_add);
    	
    	alert.setPositiveButton(sMessage, new OnClickListener() {
			
			@Override
			public void onClick(DialogInterface dialog, int which) {
				
				int time = ExerciseUnit.convert(npMins.getValue(), npSecs.getValue(), true);
				Rest myRest = new Rest(time);
				
				if (myRest.getTotalTime() > 0) {				
					if (bIndexValid) {
						mIntentExercise.setRoutineItem(mSelectedItemIndex, myRest);
					}
					else {
						mIntentExercise.AddRoutineItem(myRest);
					}
					
	    	  		mAdapter.notifyDataSetChanged();
				}
				else {
					Toast toast = Toast.makeText(getApplicationContext(), 
							getString(R.string.string_zero_time), Toast.LENGTH_SHORT);
					toast.setGravity(Gravity.TOP | Gravity.CENTER, 0, 30);
					toast.show();
				}
			}
		});
    	
    	alert.setNegativeButton(getString(R.string.string_cancel), new OnClickListener() {
			
			@Override
			public void onClick(DialogInterface dialog, int which) {			
			}
		});
	        	
    	alert.setView(viewRest);    	
    	alert.show();
	}
	
    
	private boolean isWorkoutNameUnique (String title) {
    	Log.i(TAG, "isWorkoutNameUnique");
    	
    	WorkoutDatabase database = null;
    	
    	try {
			database = WorkoutDatabaseSingleton.getDatabase(this);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
    
    	//checks to see if a workout of the same title already exists
    	if(database.doesEntryExist(title))
    	{
    		if (getIntent().hasExtra(INTENT_NAME_WORKOUT))
    		{
        		Exercise oldWorkout = getIntent().getParcelableExtra(INTENT_NAME_WORKOUT);
        		
    			if(oldWorkout.getTitle().equals(title))
    				return true;        		
    		}
    	}	
    	else
    		return true;
    	
    	return false;
	}
    
    /**
     * Send workout back to parent activity ManageWorkoutActivity
     * @return true if successful
     */
	private boolean sendResultToManageWorkoutActivity() {
    	Log.i(TAG, "sendResultToManageWorkoutActivity");
    	
    	String name = ((TextView) findViewById(R.id.edit_workout_name)).getText().toString();
    	
    	if (!isWorkoutNameUnique(name)) {
    		Toast toast = Toast.makeText(getApplicationContext(), 
					getString(R.string.string_duplicate_workout), Toast.LENGTH_SHORT);
			toast.setGravity(Gravity.TOP | Gravity.CENTER, 0, 30);
			toast.show();
			
			TextView txtName = (TextView) findViewById(R.id.edit_workout_name);        			
			txtName.clearFocus();
			txtName.setSelectAllOnFocus(true);
			txtName.requestFocus();
			
			return false;
    	}
    	
    	if(mIntentExercise.getRoutine().size()  < 1) {
    		Toast toast = Toast.makeText(getApplicationContext(), 
					getString(R.string.string_empty_workout), Toast.LENGTH_SHORT);
			toast.setGravity(Gravity.TOP | Gravity.CENTER, 0, 30);
			toast.show();
					
			return false;
    	}
    	
    	mIntentExercise.setTitle(name);
		    		
    	Intent intent = new Intent(this, ManageWorkoutActivity.class);
    	intent.putExtra(INTENT_NAME_WORKOUT, mIntentExercise);
    	
    	setResult(Activity.RESULT_OK, intent);
    	
		return true;
    }

	
    private void moveListItem(int from, int to) {
    	Log.i(TAG, "moveListItem");
    	    	
        ExerciseUnit obj_from = mIntentExercise.RemoveRoutineItem(from);
        mIntentExercise.InsertRoutineItem(to, obj_from);
        
        TouchInterceptor listview = (TouchInterceptor) findViewById(R.id.edit_workout_list);
        listview.setAdapter(mAdapter);
        
        //mAdapter.notifyDataSetChanged();    	
	}
	
    
	private void removeListItem(int which) {
		Log.i(TAG, "removeListItem");
		
		mIntentExercise.RemoveRoutineItem(which);
		mAdapter.notifyDataSetChanged();
	}
	
		
	public static interface ChangeListener {
		public void change(Exercise tempExercise);
	}
    
	
    private TouchInterceptor.DragListener mDragListener =
            new TouchInterceptor.DragListener() {
    		
	            public void drag(int from, int to) {
	                Log.i(TAG, "Drag from "+ from +" to "+ to);
	            }
            };
    
    
    private TouchInterceptor.DropListener mDropListener =
        new TouchInterceptor.DropListener() {
    	
	        public void drop(int from, int to) {
	            Log.i(TAG, "Drop from "+ from +" to "+ to);
	            moveListItem(from, to);
	
	            if (mChangeListener != null)
	                mChangeListener.change(mIntentExercise);
	        }
        };
    
    
    private OnItemClickListener mClickListener =  new OnItemClickListener() {

		public void onItemClick(AdapterView<?> parent, View view,
				int position, long id) {
			
			view.setSelected(true);
    		
			mSelectedItemIndex = position;
			
			mMode = startActionMode(new ActionModeListItemSelect());
			
			int doneButtonId = Resources.getSystem().getIdentifier("action_mode_close_button", "id", "android");
			View doneButton = findViewById(doneButtonId);
			doneButton.setOnClickListener(new View.OnClickListener() {

				@Override
			    public void onClick(View v) {					
					finishActionMode(true);
			    }
			});
		}
	};
    
	
	private void finishActionMode(boolean clearListIndex) {
    	Log.i(TAG, "finishActionMode");
    	
    	ListView listview = (ListView)findViewById(R.id.edit_workout_list);
    	listview.clearChoices();
    	listview.requestLayout();
    	mMode.finish();
    	
    	if (clearListIndex)
    		mSelectedItemIndex = INVALID_LIST_INDEX;
    }
	
	
	/**
	 * ActionMode gets called whenever a list item is selected
	 */
    private final class ActionModeListItemSelect implements ActionMode.Callback {
        
    	@Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {       	            
        	getSupportMenuInflater().inflate(R.menu.activity_edit_workout_action_mode, menu);        	             
            return true;
        }

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return false;
        }

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
	        	
	        switch (item.getItemId()) {
	        
	        	case R.id.menu_edit_exercise:
	        		Log.i(TAG, "editing workout");
	        		
					editExercise();				
					finishActionMode(false);
	        		break;
	        		
	        	case R.id.menu_delete_exercise:  
	        		Log.i(TAG, "deleting workout");
	        		
	        		AlertDialog.Builder helpBuilder = new AlertDialog.Builder(EditWorkoutActivity.this);
            		
            		helpBuilder.setTitle(getString(R.string.string_delete) + getString(R.string.string_question_mark));
            		                		
            		helpBuilder.setNegativeButton(getString(R.string.string_confirm),
                			new DialogInterface.OnClickListener() {
                	    		public void onClick(DialogInterface dialog, int which) {
                	    			removeListItem(mSelectedItemIndex);
                	    			finishActionMode(true);
                	    	    }
                	    		});
                	
                	helpBuilder.setNeutralButton(getString(R.string.string_cancel),
                			new DialogInterface.OnClickListener() {
                	    		public void onClick(DialogInterface dialog, int which) {
                	    			finishActionMode(true);
                	    	    }
                	    		});
	        		
                	AlertDialog helpDialog = helpBuilder.create();
                	helpDialog.show();  
                	
                	break;
	        }	        		        		        		
        	                                    
            return true;
        }

        @Override
        public void onDestroyActionMode(ActionMode mode) {
        	Log.i(TAG, "onDestroyActionMode");
        }                
    }
    
    
}
